package com.zdy.ws.ws.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.zdy.ws.ws.constant.TioConstant;
import com.zdy.ws.ws.enums.ResultEnum;
import com.zdy.ws.ws.constant.MsgTypeConstant;
import com.zdy.ws.ws.dto.MessageInput;
import com.zdy.ws.ws.dto.MessageOutput;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.tio.core.ChannelContext;
import org.tio.core.Tio;
import org.tio.http.common.HttpRequest;
import org.tio.http.common.HttpResponse;
import org.tio.websocket.common.WsRequest;
import org.tio.websocket.server.handler.IWsMsgHandler;

import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;

/**
 * <p>
 * tio实现类
 * </p>
 *
 * @author zdy
 * @date 2021/12/20
 */
@Slf4j
@Component
@org.tio.common.starter.annotation.TioServerMsgHandler
public class TioServerMsgHandler implements IWsMsgHandler {

    /**
     * 握手
     *
     * @param httpRequest    请求
     * @param httpResponse   响应
     * @param channelContext 通道
     * @return 响应
     * @throws Exception 异常
     */
    @Override
    public HttpResponse handshake(HttpRequest httpRequest, HttpResponse httpResponse, ChannelContext channelContext) throws Exception {
        // userId
        String userId = httpRequest.getParam(TioConstant.USER_ID);
        Tio.bindUser(channelContext, userId);
        // 绑定群组
        Tio.bindGroup(channelContext.tioConfig, userId, TioConstant.ALL_USER);
        return httpResponse;
    }

    /**
     * 完成握手后
     *
     * @param httpRequest    请求
     * @param httpResponse   响应
     * @param channelContext 通道
     * @throws Exception 异常
     */
    @Override
    public void onAfterHandshaked(HttpRequest httpRequest, HttpResponse httpResponse, ChannelContext channelContext) throws Exception {
        log.info("已连接成功");
    }

    /**
     * 收到字节信息
     *
     * @param wsRequest      请求
     * @param bytes          字节数组
     * @param channelContext 通道
     * @return ByteBuffer
     * @throws Exception 异常
     */
    @Override
    public Object onBytes(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
        String text = new String(bytes, StandardCharsets.UTF_8);
        log.info("收到byte消息:{},{}", bytes, text);
        ByteBuffer buffer = ByteBuffer.allocate(bytes.length);
        buffer.put(bytes);
        return buffer;
    }

    /**
     * 通道关闭
     *
     * @param wsRequest      请求
     * @param bytes          字节数组
     * @param channelContext 通道
     * @return 空对象
     * @throws Exception 异常
     */
    @Override
    public Object onClose(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) throws Exception {
        Tio.remove(channelContext, "close");
        return null;
    }

    /**
     * 收到文本消息
     *
     * @param wsRequest      请求
     * @param text           内容
     * @param channelContext 通道
     * @return 响应内容
     * @throws Exception 异常
     */
    @Override
    public Object onText(WsRequest wsRequest, String text, ChannelContext channelContext) throws Exception {
        log.info("收到text消息:{}", text);
        JSON msgJson = JSON.parseObject(text);
        MessageInput messageInput = JSON.toJavaObject(msgJson, MessageInput.class);
        // 心跳消息
        MessageOutput.MessageOutputBuilder builder = MessageOutput.builder();
        if (MsgTypeConstant.PING == messageInput.getMsgType()) {
            builder.code(ResultEnum.PING_SUCCESS.getCode())
                    .message(ResultEnum.PING_SUCCESS.getMsg())
                    .data(null);
        } else {
            //取到消息内容做业务处理
            builder.code(ResultEnum.MESSAGE_SUCCESS.getCode())
                    .message(ResultEnum.MESSAGE_SUCCESS.getMsg())
                    .data(null);
        }
        MessageOutput output = builder.build();
        return JSON.toJSONString(output, SerializerFeature.WriteMapNullValue);
    }
}
